package com.zsjt.yysapi.core.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zsjt.yysapi.common.constant.Constants;
import com.zsjt.yysapi.common.exception.CustomException;
import com.zsjt.yysapi.common.exception.user.CaptchaException;
import com.zsjt.yysapi.common.exception.user.CaptchaExpireException;
import com.zsjt.yysapi.common.exception.user.UserPasswordNotMatchException;
import com.zsjt.yysapi.common.util.DateUtils;
import com.zsjt.yysapi.common.util.ServletUtils;
import com.zsjt.yysapi.common.util.StringUtils;
import com.zsjt.yysapi.common.util.ip.IpUtils;
import com.zsjt.yysapi.common.util.redis.RedisCache;
import com.zsjt.yysapi.core.mapper.SysUserInfoMapper;
import com.zsjt.yysapi.core.model.LoginUser;
import com.zsjt.yysapi.core.param.sysUser.LoginParam;
import com.zsjt.yysapi.core.param.sysUser.RegisterParam;
import com.zsjt.yysapi.core.pojo.SysUser;
import com.zsjt.yysapi.core.mapper.SysUserMapper;
import com.zsjt.yysapi.core.pojo.SysUserInfo;
import com.zsjt.yysapi.core.service.SysUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zsjt.yysapi.core.util.SecurityUtils;
import com.zsjt.yysapi.core.util.TokenService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;

/**
 * <p>
 * 用户信息表 服务实现类
 * </p>
 *
 * @author zsq
 * @since 2021-07-09
 */
@Service
@Transactional
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    @Autowired
    private RedisCache redisCache;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysUserInfoMapper sysUserInfoMapper;
    @Autowired
    private TokenService tokenService;
    @Resource
    private AuthenticationManager authenticationManager;

    @Override
    public String register(RegisterParam registerParam) {
        /*验证码*/
        String verifyKey = Constants.CAPTCHA_CODE_KEY + registerParam.getUuid();
        String captcha = redisCache.getCacheObject(verifyKey);
        if (captcha == null) {
//            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
            throw new CaptchaExpireException();
        }
        if (!captcha.equalsIgnoreCase(registerParam.getCaptcha())) {
//            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
            throw new CaptchaException();
        }
        QueryWrapper<SysUser> wrapper = new QueryWrapper<>();
        wrapper.eq("user_name", registerParam.getPhone());
        if (StringUtils.isNotEmpty(registerParam.getPhone()) && sysUserMapper.selectCount(wrapper) > 0) {
            throw new CustomException("手机号" + registerParam.getPhone() + "已存在");
        }
        SysUser sysUser = new SysUser()
                .setUserName(registerParam.getPhone())
                .setNickName("默认昵称")
                .setUserType("01")
                .setPhonenumber(registerParam.getPhone())
                .setAvatar("/avatar.jpg")
                .setPassword(SecurityUtils.encryptPassword(registerParam.getPassword()))
                .setCreateBy("user")
                .setCreateTime(new Date())
                .setUpdateBy("user")
                .setUpdateTime(new Date())
                .setRemark("app用户");
        sysUserMapper.insert(sysUser);
        SysUserInfo sysUserInfo = new SysUserInfo()
                .setUserId(sysUser.getUserId())
                .setName(registerParam.getName())
                .setIdNumber(registerParam.getIdNumber())
                .setFrontImg(registerParam.getFrontImg())
                .setReverseImg(registerParam.getReverseImg())
                .setProvinceId(registerParam.getProvinceId())
                .setCityId(registerParam.getCityId())
                .setDistrictId(registerParam.getDistrictId())
                .setTownshipId(registerParam.getTownshipId());
        sysUserInfoMapper.insert(sysUserInfo);
        //构建LoginUser
        LoginUser loginUser = new LoginUser(sysUserMapper.iSelectById(sysUser.getUserId()), null);
        String token = tokenService.createToken(loginUser);
        //删除验证码缓存
        redisCache.deleteObject(verifyKey);
        return token;
    }

    /**
     * @param loginParam
     * @return
     */
    @Override
    public String login(LoginParam loginParam) {
        // 用户验证
        Authentication authentication;
        try {
            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
            authentication = authenticationManager
                    .authenticate(new UsernamePasswordAuthenticationToken(loginParam.getUserName(), loginParam.getPassword()));
        } catch (Exception e) {
            if (e instanceof BadCredentialsException) {
//                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
                throw new UserPasswordNotMatchException();
            } else {
//                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
                throw new CustomException(e.getMessage());
            }
        }
//        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        recordLoginInfo(loginUser.getUser());
        // 生成token
        return tokenService.createToken(loginUser);
    }

    /**
     * 用户信息
     *
     * @return
     */
    @Override
    public SysUser userInfo() {
        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
        return loginUser.getUser();
    }

    /**
     * 记录登录信息
     */
    public void recordLoginInfo(SysUser user) {
        user.setLoginIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
        user.setLoginDate(DateUtils.getNowDate());
        sysUserMapper.updateById(user);
    }
}
